package com.elecbook.auth.config;

import com.elecbook.auth.config.properties.OauthServerProperties;
import com.elecbook.auth.service.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;

import javax.annotation.Resource;

/**
 * description 认证服务器配置类
 *
 * @author zken
 * CreateDate 2024/11/1 14:17:27
 * -
 * 你需要根据认证服务器的配置进行url的访问，才能进行登录，否则，你的登录必然是无效的
 * <p>
 * 你需要注意的是，这里的secert密码是明文
 * <p>
 * http://localhost:8080/oauth/authorize?response_type=code&client_id=client&client_secret=secret&redirect_uri=https://www.baidu.com
 * <p>
 * 只有正确的 请求地址，才会出现授权页面，是否授权给某一个网页
 * <p>
 * 可能会遇到的问题：
 * 如果你发现：authorization_code的访问方式出现些许错误，
 * 此时，需要查阅oauth的官方请求方式，规范化自己的请求，检查一下自身的请求是否漏掉的一些参数
 */
@Configuration
@EnableAuthorizationServer
public class CustomAuthenticationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Resource
    PasswordEncoder passwordEncoder;

    @Resource(name = "authorizationServerTokenServicesCustom")
    private AuthorizationServerTokenServices authorizationServerTokenServices;

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    UserServiceImpl userService;


    @Autowired
    OauthServerProperties oauthServerProperties;

    /**
     * description 认证服务器配置类
     *
     * @author zken
     * CreateDate 2024/11/1 14:22:24
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
        clients.inMemory()// 使用in-memory存储
                .withClient("client")// client_id
                // 服务器端口处的encoder一定是需要加密过后的，如果未进行加密，会直接进行报错，redirect到login去
                .secret(passwordEncoder.encode("secret"))//客户端密钥
                // 设置一个资源id
                .resourceIds(oauthServerProperties.getResourceIds().toArray(new String[0]))
                .redirectUris("https://www.baidu.com")
                .authorizedGrantTypes("authorization_code", "password", "refresh_token")// 该client允许的授权类型authorization_code,password,refresh_token,implicit,client_credentials
                .scopes("all")// 允许的授权范围
        //客户端接收授权码的重定向地址，会有一个询问参数进行返回
        ;
    }

    /**
     * description 配置内容，设置认证管理器，这里的认证管理器是默认的
     * 配置token的令牌管理服务，将令牌的管理服务设置为内置的管理服务
     *
     * @author zken
     * CreateDate 2024/11/1 22:24:41
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints
                .authenticationManager(authenticationManager)//认证管理器
                .tokenServices(authorizationServerTokenServices)//令牌管理服务
                .userDetailsService(userService)
                .allowedTokenEndpointRequestMethods(HttpMethod.POST);
    }

    //令牌端点的安全配置
    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) {
        security
                .tokenKeyAccess("permitAll()")                    //oauth/token_key是公开
                .checkTokenAccess("permitAll()")                  //oauth/check_token公开
                .allowFormAuthenticationForClients()                //表单认证（申请令牌）
        ;
    }
}
